类何时会被加载
先来看第一个问题:如果一个类没有在程序中的任何地方被使用,它会被加载吗?
答案是:不会!
如果一个类没有在任何地方使用它是不会被类加装器加载的。哪怕是在代码中通过 import
引入,也不会被类加载器加载。
跟踪类的加载
如何判断一个类是否被类加装器加载?
我们可以通过 -verbose:class
来跟踪类的加加载情况,这个参数会输出类加载的详细信息到标准输出或日志文件中。
来看一个具体的实例:
package tech.devguide.reflection.classload.model
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
只通过 import
引入,不使用的情况:
package tech.devguide.reflection.classload;
import tech.devguide.reflection.classload.model.User;
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println("Hello world");
}
}
控制台日志(仅过滤 tech.devguide 包下的加装记录):
[0.115s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
修改上面的方法,在 main()
方法中创建一个 User
实例。
package tech.devguide.reflection.classload;
import tech.devguide.reflection.classload.model.User;
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println("Hello world");
User user = new User();
}
}
然后再观察控制台日志:
[0.096s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
[0.097s][info][class,load] tech.devguide.reflection.classload.model.User source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
由此可以判断,类是在使用的时候才被加载的。
跟反射的关系
反射是在程序运行时动态的创建类或者调用对象的方法。也就是说,如果通过反射动态的来创建一个类,那这个类的加载过程将发生在反射处理阶段。
package tech.devguide.reflection.classload;
import tech.devguide.reflection.classload.model.User;
public class ClassLoadTest {
public static void main(String[] args) {
System.out.println("Hello world");
Class.forName("tech.devguide.reflection.classload.model.User");
}
}
控制台日志:
[0.127s][info][class,load] tech.devguide.reflection.classload.ClassLoadTest source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
Hello world
[0.128s][info][class,load] tech.devguide.reflection.classload.model.User source: file:/D:/IdeaProjects/DevGuideCodes/target/classes/
这里是我们需要注意的一个点,当我们使用反射来实例化一个类,或者获取类信息时,如果类并没有被加载,会有一个类加载的过程。
但是当我们在讨论反射的性能时,这个过程并不能计算在内。因为当我们第一次创建某个对象的实例时,同样也会有类加载的过程。